﻿//-----------------------------------------------------------------------
// <copyright file="RangersNewsFeed.cs" company="Microsoft Corporation">
//     Copyright Microsoft Corporation. All Rights Reserved. This code released under the terms of the Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.) This is sample code only, do not use in production environments.
// </copyright>
//-----------------------------------------------------------------------

namespace Microsoft.ALMRangers.VsarTreasureMap.WindowsStoreApp.News
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using Windows.Web.Syndication;

    /// <summary>
    /// Defines the class which handles retrieval of RSS feeds.
    /// </summary>
    internal class RangersNewsFeed
    {
        /// <summary>
        /// The closing paragraph break tag
        /// </summary>
        private Regex closingParagraphBreakTag = new Regex("</?[pP]>");

        /// <summary>
        /// The line break tag
        /// </summary>
        private Regex lineBreakTag = new Regex("</?[bB][rR]/?>");

        /// <summary>
        /// The tag remover regex
        /// </summary>
        private Regex tagRemoverRegex = new Regex("<.*?>");

        /// <summary>
        /// Initializes a new instance of the <see cref="RangersNewsFeed"/> class.
        /// </summary>
        public RangersNewsFeed()
        {
            this.Items = new SortedSet<NewsStory>(new NewsStoryComparer());
        }

        /// <summary>
        /// Gets or sets the items.
        /// </summary>
        /// <value>The items.</value>
        public SortedSet<NewsStory> Items { get; set; }

        /// <summary>
        /// Loads the items async.
        /// </summary>
        /// <returns>Task.</returns>
        public async Task LoadItemsAsync()
        {
            this.Items.Clear();
            var client = new SyndicationClient();
            var tasks = (from url in App.Database.NewsUrls
                         select client.RetrieveFeedAsync(url).AsTask()).ToList();

            while (tasks.Count > 0)
            {
                var nextTask = await Task.WhenAny(tasks);
                if (nextTask.Status == TaskStatus.RanToCompletion)
                {
                    this.ParseSyndicationFeed(nextTask.Result);
                }

                tasks.Remove(nextTask);
            }
        }

        /// <summary>
        /// Cleanups the specified content.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <returns>System.String.</returns>
        private string Cleanup(string content)
        {
            var result = this.lineBreakTag.Replace(content, Environment.NewLine);
            result = this.closingParagraphBreakTag.Replace(result, Environment.NewLine);
            result = this.tagRemoverRegex.Replace(result, string.Empty);
            result = result.Replace("&amp;", "&");
            return result.Trim();
        }

        /// <summary>
        /// Parses the syndication feed.
        /// </summary>
        /// <param name="syndicationFeed">The syndication feed.</param>
        private void ParseSyndicationFeed(SyndicationFeed syndicationFeed)
        {
            foreach (var item in syndicationFeed.Items)
            {
                this.Items.Add(new NewsStory()
                 {
                     Id = item.Id,
                     Title = item.Title.Text,
                     Published = item.PublishedDate.DateTime,
                     Author = item.Authors.Aggregate<SyndicationPerson, string>(
                         string.Empty,
                         (current, next) =>
                         {
                             if (current.Length > 0)
                             {
                                 current += ", ";
                             }

                             current += next.NodeValue;

                             return current;
                         }),
                     Content = this.Cleanup(item.Summary.Text),
                     Link = item.Links[0].Uri
                 });
            }
        }
    }
}
